#pragma once

#include <Windows.h>
#include <gl\GL.h>

#include <glut.h>

#include <vector>
#include <exception>
#include <string>

#include <boost\bind.hpp>
#include <boost\signal.hpp>

#include <IL\il.h>
#include <IL\ilu.h>
#include <IL\ilut.h>

namespace TUMAR { namespace Render
{
	class AbstractRenderer
	{
	protected:
		void glMultTransposedMatrix(const float* matrix);

		GLuint LoadTexture(std::string file);
	public:
		boost::signal<void ()> Invalidate;

		virtual void Init(void);

		virtual void Resize(int width, int height);

		virtual void Render(void) = 0;
	};

	class TimerCallback
	{
	private:
		static std::vector<TimerCallback*> instances;
		static int AddInstance(TimerCallback* instance);
		static void RemoveInstance(TimerCallback* instance);

		static void glutTimerCallback(int instance);

		int stop;
		int scheduled;

		int interval;
		int instance;

		void Schedule();
	public:
		TimerCallback(void);
		virtual ~TimerCallback(void);

		void Schedule(int interval);

		void Stop();

		virtual void Tick(void) const = 0;
	};

	class RenderSystem
	{
	private:
		static RenderSystem* instance;
		static void glutRenderCallback(void);
		static void glutResizeCallback(int width, int height);
		static void glutKeyboardCallback(unsigned char key, int x, int y);

		std::vector<AbstractRenderer*> renderer;
		void Resize(int width, int height);
		void Render(void);
	public:
		boost::signal<void (unsigned char)> KeyPressed;

		RenderSystem(void);
		~RenderSystem(void);

		void Init(int argc, char* argv[]);
		void StartRenderLoop(void);

		void AddRenderer(AbstractRenderer* renderer);
	};
}}

